package is2.minga.packetProcessor;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import is2.minga.packetProcessor.formatValidator.*;
import is2.minga.packetProcessor.authentificator.*;
import is2.minga.packetProcessor.internalFormatWrapper.*;
import is2.misc.pipeAndFilter.FilterProcess;
import is2.misc.pipeAndFilter.PipeConnector;



public class PacketProcessor
{
		
	private Integer  outPacketizerControlPort;
	private String outPacketizerHost;
	private Integer moduleNumber;
	
	public PacketProcessor(Integer inDataPort, String outPacketizerHost, 
			Integer outPacketizerControlPort, String outModuleHost, Integer outModulePort,
			Integer moduleNumber)
	{
		
		this.outPacketizerHost = outPacketizerHost;
		this.outPacketizerControlPort = outPacketizerControlPort;
		this.moduleNumber = moduleNumber;
		
		// crea pipes
		PipeConnector<String> pipe1 = new PipeConnector<String>();
		PipeConnector<String> pipe2 = new PipeConnector<String>();
		PipeConnector<String> pipe3 = new PipeConnector<String>();
		PipeConnector<String> pipe4 = new PipeConnector<String>();
		
		
		//inicio del pipe
		Runnable run_in = new InPacketProcessor(pipe1, inDataPort);
		Thread threadIn = new Thread(run_in);
		threadIn.start();
		
		// format validator
		Runnable run_fv = new FilterProcess<String, String>(new FormatValidator(), pipe1, pipe2);
		Thread threadFv = new Thread(run_fv);
		threadFv.start();
		
		// autenticator
		Runnable run_aut = new FilterProcess<String, String>(new MingaAuthentificator(), pipe2, pipe3);
		Thread threadAut = new Thread(run_aut);
		threadAut.start();
		
		// internal format wrapper
		Runnable run_fw = new FilterProcess<String, String>(new InternalFormatWrapper(), pipe3, pipe4);
		Thread threadFw = new Thread(run_fw);
		threadFw.start();
		
						
		// fin del pipe
		Runnable rout = new OutPacketProcessor(pipe4, outModuleHost, outModulePort);
		Thread threadOut = new Thread(rout);
		threadOut.start();
		
		notificarEstado();
		System.out.println("packet processor " + String.valueOf(moduleNumber) + " iniciado");

		
	}
	

	
	public static void main (String[]arg) 
	{
		// recibe por parametro el archivo de configuracion
		
		Integer inDataPort = 0;
		String outPacketizerHost ="", outModuleHost = "";
		Integer outPacketizerControlPort = 0;
		Integer outModulePort = 0;
		Integer moduleNumber = 0 ;
		
	
		try {

			// levanta cual es el archivo de configuracion a cargar 
			// esto permite soportar varias instancias con distintas configuraciones
			String RUN_CONFIG_FILE = "config/RUN_CONFIG.txt";
		    FileInputStream fstream1 = new FileInputStream(RUN_CONFIG_FILE);
		    DataInputStream in1 = new DataInputStream(fstream1);
		    BufferedReader br1 = new BufferedReader(new InputStreamReader(in1));
		    String configFile = br1.readLine();
			
			// levanta el archivo de configuracion indicado arriba
		    FileInputStream fstream = new FileInputStream(configFile);
		    DataInputStream in = new DataInputStream(fstream);
		    BufferedReader br = new BufferedReader(new InputStreamReader(in));
		    String strLine;
		 	String value;   
		    strLine = br.readLine();
		    		    
		    while (strLine != null)   
		    {
		    	value = strLine.split(":")[1];
				
		    	if (strLine.contains("inDataPort"))
		    	{
		    		inDataPort = Integer.parseInt(value);
		    	}
		    	else if (strLine.contains("outPacketizerHost"))
		    	{
		    		outPacketizerHost = value;
		    	}
		     	else if (strLine.contains("outModuleHost"))
		    	{
		     		outModuleHost = value;
		    	}
		    	else if (strLine.contains("outPacketizerControlPort"))
		    	{
		    		outPacketizerControlPort = Integer.parseInt(value);
		    	}		    	
		    	else if (strLine.contains("outModulePort"))
		    	{
		    		outModulePort = Integer.parseInt(value);
		    	}		    	
		    	else if (strLine.contains("instanceNumber"))
		    	{
		    		moduleNumber = Integer.parseInt(value);
		    	}		    	
	
			    	
		    	strLine = br.readLine();
		    	
		    }
		    in.close();

					
			new PacketProcessor(inDataPort, outPacketizerHost, 
					outPacketizerControlPort, outModuleHost, outModulePort, moduleNumber);
			
			
		} catch (Exception e) {
			System.err.println(e.toString());
	 }
	
	}		



	private void notificarEstado()
	{
	   
    	try 
    	{
		    Socket clientSocket = new Socket(outPacketizerHost, outPacketizerControlPort);
			PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(), true);
			outToServer.println("modulo" + String.valueOf(moduleNumber) +"UP");
			//clientSocket.close();

    	} catch (Exception e)     	{
    		System.out.println("packetizer offline para notificar estado");
    	}
	}
}

